// LockFreeStack.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "LockFreeStack.h"
#include <iostream>
#include "SharedPtr.h"

DWORD WINAPI ThreadFunc(LPVOID stack)
{
	LockFreeStack<int>* freeLockStack = (LockFreeStack<int>*)stack;
	for (int i = 0; i < 20000; ++i)
	{
		freeLockStack->Push(i);
	}

	return 0;
}

DWORD WINAPI ThreadFuncShow(LPVOID stack)
{
	LockFreeStack<int>* freeLockStack = (LockFreeStack<int>*)stack;

	for (size_t i = 0; i < 15000; ++i)
	{ 
		SharedPtr<int> value(freeLockStack->Pop());
		if (value.Get())
		{
			//std::cout << *value << " ";
		}
	}
	std::cout << std::endl;

	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	LockFreeStack<int> freeLockStack;

	DWORD dwThreadId = 0;

	HANDLE hThreadPush1 = CreateThread(NULL, 0,	ThreadFunc, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);
	HANDLE hThreadPush2 = CreateThread(NULL, 0,	ThreadFunc, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);
	HANDLE hThreadPush3 = CreateThread(NULL, 0,	ThreadFunc, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);

	HANDLE hThreadShow1 = CreateThread(NULL, 0,	ThreadFuncShow, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);
	HANDLE hThreadShow2 = CreateThread(NULL, 0,	ThreadFuncShow, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);
	HANDLE hThreadShow3 = CreateThread(NULL, 0,	ThreadFuncShow, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);
	HANDLE hThreadShow4 = CreateThread(NULL, 0,	ThreadFuncShow, &freeLockStack, CREATE_SUSPENDED, &dwThreadId);

	ResumeThread(hThreadPush1);
	ResumeThread(hThreadPush2);
	ResumeThread(hThreadPush3);

	WaitForSingleObject(hThreadPush1, INFINITE);
	WaitForSingleObject(hThreadPush2, INFINITE);
	WaitForSingleObject(hThreadPush3, INFINITE);

	ResumeThread(hThreadShow1);
	ResumeThread(hThreadShow2);
	ResumeThread(hThreadShow3);
	ResumeThread(hThreadShow4);

	WaitForSingleObject(hThreadShow1, INFINITE);
	WaitForSingleObject(hThreadShow2, INFINITE);
	WaitForSingleObject(hThreadShow3, INFINITE);
	WaitForSingleObject(hThreadShow4, INFINITE);
	CloseHandle(hThreadPush1);
	CloseHandle(hThreadPush2);
	CloseHandle(hThreadPush3);
	CloseHandle(hThreadShow1);
	CloseHandle(hThreadShow2);
	CloseHandle(hThreadShow3);
	CloseHandle(hThreadShow4);

	Sleep(1000);

	return 0;
}

